package carassius.GUI;

import carassius.BLL.DateTimeHelper;
import carassius.BLL.Events.Aquarium.AquariumAddedListener;
import carassius.BLL.Events.Aquarium.AquariumRemovedListener;
import carassius.BLL.Events.OrganismList.OrganismListAddedListener;
import carassius.BLL.Events.OrganismList.OrganismListRemovedListener;
import carassius.BLL.Events.WaterMeasurement.WaterMeasurementAddedListener;
import carassius.BLL.Events.WaterMeasurement.WaterMeasurementRemovedListener;
import carassius.BLL.Events.WaterRefreshment.WaterRefreshmentAddedListener;
import carassius.BLL.Events.WaterRefreshment.WaterRefreshmentRemovedListener;
import carassius.DAL.ActionRow;
import carassius.DAL.AquariumRow;
import carassius.DAL.Database;
import carassius.DAL.OptimalAquariumWaterConditionRow;
import carassius.DAL.OrganismListRow;
import carassius.DAL.WaterMeasurementListRow;
import carassius.DAL.WaterMeasurementRow;
import carassius.DAL.WaterRefreshmentRow;
import java.awt.Component;
import java.awt.Window;
import java.beans.PropertyChangeEvent;
import java.beans.PropertyChangeListener;
import java.sql.SQLException;
import java.util.AbstractMap.SimpleEntry;
import java.util.ArrayList;
import java.util.GregorianCalendar;
import java.util.ResourceBundle;
import javax.swing.DefaultListModel;
import javax.swing.JOptionPane;
import javax.swing.event.ChangeEvent;
import javax.swing.event.ChangeListener;
import javax.swing.table.DefaultTableModel;

/**
 *
 * @author siebz0r
 */
public class MainForm
		extends javax.swing.JFrame
		implements AquariumAddedListener,
				   AquariumRemovedListener,
				   OrganismListAddedListener,
				   OrganismListRemovedListener,
				   WaterMeasurementAddedListener,
				   WaterMeasurementRemovedListener,
				   WaterRefreshmentAddedListener,
				   WaterRefreshmentRemovedListener,
				   PropertyChangeListener,
				   ChangeListener
{
	//<editor-fold defaultstate="collapsed" desc="Constructors">
	public MainForm()
	{
		initComponents();

		//temporarely disable unfinished features
		uxPlantsTabPanel.setVisible(false);
		uxMainTabbedPane.remove(uxPlantsTabPanel);
		uxNotesPanel.setVisible(false);

		//hide water values
		uxWaterValuesScrollPane.setVisible(false);

		//fill the aquarium list with available aquaria
		fillAquariumList();

		Database.getAquariumTable().addAquariumAddedEventListener(this);
		Database.getAquariumTable().addAquariumRemovedEventListener(this);

		Database.getOrganismListTable().addOrganismListAddedEventListener(this);
		Database.getOrganismListTable().addOrganismListRemovedEventListener(this);

		Database.getWaterMeasurementTable().addWaterMeasurementAddedEventListener(this);
		Database.getWaterMeasurementTable().addWaterMeasurementRemovedEventListener(this);

		Database.getWaterRefreshmentTable().addWaterRefreshmentAddedEventListener(this);
		Database.getWaterRefreshmentTable().addWaterRefreshmentRemovedEventListener(this);

		uxCalendarPanel.addPropertyChangeListener("year", this);
		uxCalendarPanel.addPropertyChangeListener("month", this);
		uxCalendarPanel.addPropertyChangeListener("day", this);
		uxMainTabbedPane.addChangeListener(this);
		uxWaterActionList.setSelectedDate(uxCalendarPanel.getDate());
	}
	//</editor-fold>

	//<editor-fold defaultstate="collapsed" desc="Private methods">
	/**
	 * Clears and fills uxAquariumList with all available aquaria.
	 */
	private void fillAquariumList()
	{
		DefaultListModel model = (DefaultListModel) uxAquariumList.getModel();
		model.clear();
		try
		{
			for (AquariumRow r : Database.getAquariumTable().getAll())
			{
				model.addElement(r);
			}
		}
		catch (SQLException ex)
		{
			JOptionPane.showMessageDialog(this,
					ResourceBundle.getBundle("carassius.resources.Messages").getString("AddAquariumError"),
					ResourceBundle.getBundle("carassius.resources.Messages").getString("AddAquariumErrorTitle"),
					JOptionPane.ERROR_MESSAGE);
		}
	}

	/**
	 * Clears and fills uxActionList with water refreshments and
	 * water measurements belonging to the selected aquarium in uxAquariumList
	 * and the selected date in uxCalendarPanel.
	 */
	private void fillActionList()
	{
		AquariumRow row = (AquariumRow) uxAquariumList.getSelectedValue();
		if (row != null)
		{
			try
			{
				ArrayList<ActionRow> waterActions = Database.getWaterRefreshmentTable().getByAquariumId(row.getId());
				waterActions.addAll(Database.getWaterMeasurementTable().getByAquariumId(row.getId()));

				DefaultListModel model = (DefaultListModel) uxWaterActionList.getModel();
				model.clear();

				GregorianCalendar date = uxCalendarPanel.getDate();

				GregorianCalendar rDate = new GregorianCalendar();
				for (ActionRow r : waterActions)
				{
					rDate.setTime(r.getDate());
					if (DateTimeHelper.compareDates(date, rDate))
					{
						model.addElement(r);
					}
				}
			}
			catch (SQLException ex)
			{
				//todo: handle sht
			}
		}
	}

	private void setMarkedDates()
	{
		//clear marked dates
		ArrayList<Long> markedDates = uxCalendarPanel.getMarkedDates();
		for (Long l : markedDates)
		{
			uxCalendarPanel.removeMarkedDate(l);
		}

		AquariumRow row = (AquariumRow) uxAquariumList.getSelectedValue();
		if (row != null)
		{
			try
			{
				//fetch water actions by aquarium id
				ArrayList<ActionRow> waterActions = Database.getWaterRefreshmentTable().getByAquariumId(row.getId());
				waterActions.addAll(Database.getWaterMeasurementTable().getByAquariumId(row.getId()));

				//mark dates
				for (ActionRow r : waterActions)
				{
					uxCalendarPanel.addMarkedDate(r.getDate().getTime());
				}
			}
			catch (SQLException ex)
			{
				System.out.println(ex.toString());
				System.out.println("Couldn't mark dates.");
			}
		}
	}

	/**
	 * Fills the animal tab with the animals belonging to the selected aquarium.
	 */
	private void fillAnimalTab()
	{
		if (uxMainTabbedPane.getSelectedComponent() == uxAnimalPanel
				&& uxAquariumList.getSelectedValue() instanceof AquariumRow)
		{
			try
			{
				AquariumRow aquariumRow = (AquariumRow) uxAquariumList.getSelectedValue();
				DefaultTableModel model = (DefaultTableModel) uxAnimalListTable.getModel();
				model.setRowCount(0);

				for (OrganismListRow organismListRow : Database.getOrganismListTable().getByAquariumId(aquariumRow.getId()))
				{
					addOrganismListToAnimalTable(organismListRow);
				}
			}
			catch (SQLException ex)
			{
				//todo: handle
			}
		}
	}

	private void addOrganismListToAnimalTable(OrganismListRow row)
	{
		DefaultTableModel model = (DefaultTableModel) uxAnimalListTable.getModel();
		if (row.getOrganismId() >= 0)
		{
			model.addRow(new Object[]
					{
						row
					});
		}
		int rowNumber = uxAnimalListTable.getRowCount() - 1;
		Component renderer = uxAnimalListTable.prepareRenderer(uxAnimalListTable.getCellRenderer(rowNumber, 0), rowNumber, 0);
		uxAnimalListTable.setRowHeight(rowNumber, renderer.getPreferredSize().height);
	}

	/**
	 * Remove an aquarium from uxAquariumList.
	 * @param row The aquarium to remove.
	 */
	private void removeAquariumFromList(AquariumRow row)
	{
		DefaultListModel model = (DefaultListModel) uxAquariumList.getModel();
		model.removeElement(row);
	}

	//</editor-fold>
	/** This method is called from within the constructor to
	 * initialize the form.
	 * WARNING: Do NOT modify this code. The content of this method is
	 * always regenerated by the Form Editor.
	 */
	@SuppressWarnings("unchecked")
    // <editor-fold defaultstate="collapsed" desc="Generated Code">//GEN-BEGIN:initComponents
    private void initComponents() {
        java.awt.GridBagConstraints gridBagConstraints;

        uxMainSplitPane = new javax.swing.JSplitPane();
        uxLeftPanel = new javax.swing.JPanel();
        uxAquariumPanel = new javax.swing.JPanel();
        uxAquariumScrollPane = new javax.swing.JScrollPane();
        uxAquariumList = new carassius.GUI.AquariumList();
        uxNotesPanel = new javax.swing.JPanel();
        uxNotesScrollPane = new javax.swing.JScrollPane();
        uxNotesList = new javax.swing.JList();
        uxMainTabbedPane = new javax.swing.JTabbedPane();
        uxWaterValuesTabPanel = new javax.swing.JPanel();
        uxCalendarPanel = new carassius.GUI.Calendar.CalendarPanel();
        uxActionsPanel = new javax.swing.JPanel();
        uxWaterActionsScrollPane = new javax.swing.JScrollPane();
        uxWaterActionList = new carassius.GUI.WaterActionList();
        uxActionButtonPanel = new javax.swing.JPanel();
        uxWaterTestAddButton = new javax.swing.JButton();
        uxWaterRefreshmentAddButton = new javax.swing.JButton();
        uxDetailsPanel = new javax.swing.JPanel();
        uxWaterValuesScrollPane = new javax.swing.JScrollPane();
        uxWaterValuesTable = new javax.swing.JTable();
        uxMeasurementPanel = new javax.swing.JPanel();
        uxDescriptionScrollPane = new javax.swing.JScrollPane();
        uxDescriptionTextArea = new javax.swing.JTextArea();
        uxPlantsTabPanel = new javax.swing.JPanel();
        uxAnimalPanel = new javax.swing.JPanel();
        uxAddAnimalButton = new javax.swing.JButton();
        uxAnimalListTableScrollPane = new javax.swing.JScrollPane();
        uxAnimalListTable = new carassius.GUI.AnimalListTable(this);
        uxMainMenuBar = new javax.swing.JMenuBar();
        uxFileMenu = new javax.swing.JMenu();
        uxNewMenu = new javax.swing.JMenu();
        uxNewAquariumMenuItem = new javax.swing.JMenuItem();
        uxQuitMenuItem = new javax.swing.JMenuItem();
        uxEditMenu = new javax.swing.JMenu();
        uxDatabaseMenuItem = new javax.swing.JMenuItem();
        uxHelpMenu = new javax.swing.JMenu();
        uxAboutMenuItem = new javax.swing.JMenuItem();

        setDefaultCloseOperation(javax.swing.WindowConstants.DISPOSE_ON_CLOSE);
        org.jdesktop.application.ResourceMap resourceMap = org.jdesktop.application.Application.getInstance(carassius.CarassiusApp.class).getContext().getResourceMap(MainForm.class);
        setTitle(resourceMap.getString("Form.title")); // NOI18N
        setName("Form"); // NOI18N
        getContentPane().setLayout(new java.awt.GridBagLayout());

        uxMainSplitPane.setName("uxMainSplitPane"); // NOI18N

        uxLeftPanel.setName("uxLeftPanel"); // NOI18N
        uxLeftPanel.setLayout(new java.awt.GridBagLayout());

        uxAquariumPanel.setBorder(javax.swing.BorderFactory.createTitledBorder(resourceMap.getString("uxAquariumPanel.border.title"))); // NOI18N
        uxAquariumPanel.setMinimumSize(new java.awt.Dimension(100, 50));
        uxAquariumPanel.setName("uxAquariumPanel"); // NOI18N
        uxAquariumPanel.setPreferredSize(new java.awt.Dimension(100, 50));
        uxAquariumPanel.setLayout(new java.awt.GridBagLayout());

        uxAquariumScrollPane.setName("uxAquariumScrollPane"); // NOI18N

        uxAquariumList.setModel(new DefaultListModel());
        uxAquariumList.setName("uxAquariumList"); // NOI18N
        uxAquariumList.addListSelectionListener(new javax.swing.event.ListSelectionListener() {
            public void valueChanged(javax.swing.event.ListSelectionEvent evt) {
                uxAquariumListValueChanged(evt);
            }
        });
        uxAquariumScrollPane.setViewportView(uxAquariumList);

        gridBagConstraints = new java.awt.GridBagConstraints();
        gridBagConstraints.gridx = 0;
        gridBagConstraints.gridy = 0;
        gridBagConstraints.fill = java.awt.GridBagConstraints.BOTH;
        gridBagConstraints.weightx = 1.0;
        gridBagConstraints.weighty = 1.0;
        uxAquariumPanel.add(uxAquariumScrollPane, gridBagConstraints);

        gridBagConstraints = new java.awt.GridBagConstraints();
        gridBagConstraints.fill = java.awt.GridBagConstraints.BOTH;
        gridBagConstraints.weightx = 0.5;
        gridBagConstraints.weighty = 0.5;
        uxLeftPanel.add(uxAquariumPanel, gridBagConstraints);

        uxNotesPanel.setBorder(javax.swing.BorderFactory.createTitledBorder(resourceMap.getString("uxNotesPanel.border.title"))); // NOI18N
        uxNotesPanel.setName("uxNotesPanel"); // NOI18N
        uxNotesPanel.setLayout(new java.awt.GridBagLayout());

        uxNotesScrollPane.setName("uxNotesScrollPane"); // NOI18N

        uxNotesList.setName("uxNotesList"); // NOI18N
        uxNotesScrollPane.setViewportView(uxNotesList);

        gridBagConstraints = new java.awt.GridBagConstraints();
        gridBagConstraints.gridx = 0;
        gridBagConstraints.gridy = 0;
        gridBagConstraints.fill = java.awt.GridBagConstraints.BOTH;
        gridBagConstraints.anchor = java.awt.GridBagConstraints.NORTHWEST;
        gridBagConstraints.weightx = 1.0;
        gridBagConstraints.weighty = 1.0;
        uxNotesPanel.add(uxNotesScrollPane, gridBagConstraints);

        gridBagConstraints = new java.awt.GridBagConstraints();
        gridBagConstraints.gridx = 0;
        gridBagConstraints.gridy = 1;
        gridBagConstraints.fill = java.awt.GridBagConstraints.BOTH;
        gridBagConstraints.weightx = 0.5;
        gridBagConstraints.weighty = 0.2;
        uxLeftPanel.add(uxNotesPanel, gridBagConstraints);

        uxMainSplitPane.setLeftComponent(uxLeftPanel);

        uxMainTabbedPane.setName("uxMainTabbedPane"); // NOI18N

        uxWaterValuesTabPanel.setName("uxWaterValuesTabPanel"); // NOI18N
        uxWaterValuesTabPanel.setLayout(new java.awt.GridBagLayout());

        uxCalendarPanel.setName("uxCalendarPanel"); // NOI18N
        gridBagConstraints = new java.awt.GridBagConstraints();
        gridBagConstraints.insets = new java.awt.Insets(5, 5, 0, 0);
        uxWaterValuesTabPanel.add(uxCalendarPanel, gridBagConstraints);

        uxActionsPanel.setBorder(javax.swing.BorderFactory.createTitledBorder(resourceMap.getString("uxActionsPanel.border.title"))); // NOI18N
        uxActionsPanel.setName("uxActionsPanel"); // NOI18N
        uxActionsPanel.setLayout(new java.awt.GridBagLayout());

        uxWaterActionsScrollPane.setName("uxWaterActionsScrollPane"); // NOI18N

        uxWaterActionList.setModel(new DefaultListModel());
        uxWaterActionList.setName("uxWaterActionList"); // NOI18N
        uxWaterActionList.addListSelectionListener(new javax.swing.event.ListSelectionListener() {
            public void valueChanged(javax.swing.event.ListSelectionEvent evt) {
                uxActionsListValueChanged(evt);
            }
        });
        uxWaterActionsScrollPane.setViewportView(uxWaterActionList);

        gridBagConstraints = new java.awt.GridBagConstraints();
        gridBagConstraints.gridx = 0;
        gridBagConstraints.gridy = 0;
        gridBagConstraints.fill = java.awt.GridBagConstraints.BOTH;
        gridBagConstraints.weightx = 1.0;
        gridBagConstraints.weighty = 1.0;
        uxActionsPanel.add(uxWaterActionsScrollPane, gridBagConstraints);

        uxActionButtonPanel.setBorder(javax.swing.BorderFactory.createTitledBorder(resourceMap.getString("uxActionButtonPanel.border.title"))); // NOI18N
        uxActionButtonPanel.setName("uxActionButtonPanel"); // NOI18N
        uxActionButtonPanel.setLayout(new java.awt.GridBagLayout());

        uxWaterTestAddButton.setText(resourceMap.getString("uxWaterTestAddButton.text")); // NOI18N
        uxWaterTestAddButton.setName("uxWaterTestAddButton"); // NOI18N
        uxWaterTestAddButton.addActionListener(new java.awt.event.ActionListener() {
            public void actionPerformed(java.awt.event.ActionEvent evt) {
                uxWaterTestAddButtonActionPerformed(evt);
            }
        });
        gridBagConstraints = new java.awt.GridBagConstraints();
        gridBagConstraints.gridx = 0;
        gridBagConstraints.gridy = 0;
        gridBagConstraints.anchor = java.awt.GridBagConstraints.NORTHWEST;
        uxActionButtonPanel.add(uxWaterTestAddButton, gridBagConstraints);

        uxWaterRefreshmentAddButton.setText(resourceMap.getString("uxWaterRefreshmentAddButton.text")); // NOI18N
        uxWaterRefreshmentAddButton.setName("uxWaterRefreshmentAddButton"); // NOI18N
        uxWaterRefreshmentAddButton.addActionListener(new java.awt.event.ActionListener() {
            public void actionPerformed(java.awt.event.ActionEvent evt) {
                uxWaterRefreshmentAddButtonActionPerformed(evt);
            }
        });
        gridBagConstraints = new java.awt.GridBagConstraints();
        gridBagConstraints.gridx = 1;
        gridBagConstraints.gridy = 0;
        gridBagConstraints.anchor = java.awt.GridBagConstraints.NORTHWEST;
        gridBagConstraints.insets = new java.awt.Insets(0, 5, 0, 0);
        uxActionButtonPanel.add(uxWaterRefreshmentAddButton, gridBagConstraints);

        gridBagConstraints = new java.awt.GridBagConstraints();
        gridBagConstraints.gridx = 0;
        gridBagConstraints.gridy = 1;
        gridBagConstraints.anchor = java.awt.GridBagConstraints.LAST_LINE_END;
        uxActionsPanel.add(uxActionButtonPanel, gridBagConstraints);

        gridBagConstraints = new java.awt.GridBagConstraints();
        gridBagConstraints.gridx = 1;
        gridBagConstraints.gridy = 0;
        gridBagConstraints.fill = java.awt.GridBagConstraints.BOTH;
        gridBagConstraints.anchor = java.awt.GridBagConstraints.NORTHWEST;
        gridBagConstraints.weightx = 1.0;
        gridBagConstraints.insets = new java.awt.Insets(5, 5, 0, 5);
        uxWaterValuesTabPanel.add(uxActionsPanel, gridBagConstraints);

        uxDetailsPanel.setName("uxDetailsPanel"); // NOI18N
        uxDetailsPanel.setLayout(new java.awt.GridBagLayout());

        uxWaterValuesScrollPane.setName("uxWaterValuesScrollPane"); // NOI18N

        uxWaterValuesTable.setModel(new javax.swing.table.DefaultTableModel(
            new Object [][] {

            },
            new String [] {
                "Naam", "mg/L", "min.", "max."
            }
        ) {
            Class[] types = new Class [] {
                java.lang.String.class, java.lang.Double.class, java.lang.Double.class, java.lang.Double.class
            };
            boolean[] canEdit = new boolean [] {
                false, false, false, false
            };

            public Class getColumnClass(int columnIndex) {
                return types [columnIndex];
            }

            public boolean isCellEditable(int rowIndex, int columnIndex) {
                return canEdit [columnIndex];
            }
        });
        uxWaterValuesTable.setName("uxWaterValuesTable"); // NOI18N
        uxWaterValuesScrollPane.setViewportView(uxWaterValuesTable);
        uxWaterValuesTable.getColumnModel().getColumn(0).setHeaderValue(resourceMap.getString("uxWaterValuesTable.columnModel.title0")); // NOI18N
        uxWaterValuesTable.getColumnModel().getColumn(1).setHeaderValue(resourceMap.getString("uxWaterValuesTable.columnModel.title1")); // NOI18N
        uxWaterValuesTable.getColumnModel().getColumn(2).setHeaderValue(resourceMap.getString("uxWaterValuesTable.columnModel.title2")); // NOI18N
        uxWaterValuesTable.getColumnModel().getColumn(3).setHeaderValue(resourceMap.getString("uxWaterValuesTable.columnModel.title3")); // NOI18N

        gridBagConstraints = new java.awt.GridBagConstraints();
        gridBagConstraints.gridx = 0;
        gridBagConstraints.gridy = 0;
        gridBagConstraints.fill = java.awt.GridBagConstraints.BOTH;
        gridBagConstraints.ipadx = 170;
        gridBagConstraints.anchor = java.awt.GridBagConstraints.FIRST_LINE_START;
        gridBagConstraints.weighty = 1.0;
        gridBagConstraints.insets = new java.awt.Insets(5, 5, 5, 0);
        uxDetailsPanel.add(uxWaterValuesScrollPane, gridBagConstraints);

        uxMeasurementPanel.setBorder(javax.swing.BorderFactory.createTitledBorder(resourceMap.getString("uxMeasurementPanel.border.title"))); // NOI18N
        uxMeasurementPanel.setName("uxMeasurementPanel"); // NOI18N
        uxMeasurementPanel.setLayout(new java.awt.CardLayout());

        uxDescriptionScrollPane.setName("uxDescriptionScrollPane"); // NOI18N

        uxDescriptionTextArea.setColumns(20);
        uxDescriptionTextArea.setEditable(false);
        uxDescriptionTextArea.setLineWrap(true);
        uxDescriptionTextArea.setRows(5);
        uxDescriptionTextArea.setMinimumSize(new java.awt.Dimension(0, 40));
        uxDescriptionTextArea.setName("uxDescriptionTextArea"); // NOI18N
        uxDescriptionScrollPane.setViewportView(uxDescriptionTextArea);

        uxMeasurementPanel.add(uxDescriptionScrollPane, "card2");

        gridBagConstraints = new java.awt.GridBagConstraints();
        gridBagConstraints.gridx = 1;
        gridBagConstraints.gridy = 0;
        gridBagConstraints.fill = java.awt.GridBagConstraints.BOTH;
        gridBagConstraints.anchor = java.awt.GridBagConstraints.NORTHWEST;
        gridBagConstraints.weightx = 1.0;
        gridBagConstraints.weighty = 1.0;
        gridBagConstraints.insets = new java.awt.Insets(5, 5, 5, 5);
        uxDetailsPanel.add(uxMeasurementPanel, gridBagConstraints);

        gridBagConstraints = new java.awt.GridBagConstraints();
        gridBagConstraints.gridx = 0;
        gridBagConstraints.gridy = 1;
        gridBagConstraints.gridwidth = 3;
        gridBagConstraints.fill = java.awt.GridBagConstraints.BOTH;
        gridBagConstraints.weightx = 1.0;
        gridBagConstraints.weighty = 1.0;
        uxWaterValuesTabPanel.add(uxDetailsPanel, gridBagConstraints);

        uxMainTabbedPane.addTab(resourceMap.getString("uxWaterValuesTabPanel.TabConstraints.tabTitle"), uxWaterValuesTabPanel); // NOI18N

        uxPlantsTabPanel.setName("uxPlantsTabPanel"); // NOI18N

        javax.swing.GroupLayout uxPlantsTabPanelLayout = new javax.swing.GroupLayout(uxPlantsTabPanel);
        uxPlantsTabPanel.setLayout(uxPlantsTabPanelLayout);
        uxPlantsTabPanelLayout.setHorizontalGroup(
            uxPlantsTabPanelLayout.createParallelGroup(javax.swing.GroupLayout.Alignment.LEADING)
            .addGap(0, 690, Short.MAX_VALUE)
        );
        uxPlantsTabPanelLayout.setVerticalGroup(
            uxPlantsTabPanelLayout.createParallelGroup(javax.swing.GroupLayout.Alignment.LEADING)
            .addGap(0, 402, Short.MAX_VALUE)
        );

        uxMainTabbedPane.addTab(resourceMap.getString("uxPlantsTabPanel.TabConstraints.tabTitle"), uxPlantsTabPanel); // NOI18N

        uxAnimalPanel.setName("uxAnimalPanel"); // NOI18N
        uxAnimalPanel.setLayout(new java.awt.GridBagLayout());

        uxAddAnimalButton.setText(resourceMap.getString("uxAddAnimalButton.text")); // NOI18N
        uxAddAnimalButton.setName("uxAddAnimalButton"); // NOI18N
        uxAddAnimalButton.addActionListener(new java.awt.event.ActionListener() {
            public void actionPerformed(java.awt.event.ActionEvent evt) {
                uxAddAnimalButtonActionPerformed(evt);
            }
        });
        gridBagConstraints = new java.awt.GridBagConstraints();
        gridBagConstraints.gridx = 0;
        gridBagConstraints.gridy = 0;
        gridBagConstraints.anchor = java.awt.GridBagConstraints.NORTHWEST;
        gridBagConstraints.insets = new java.awt.Insets(5, 5, 5, 5);
        uxAnimalPanel.add(uxAddAnimalButton, gridBagConstraints);

        uxAnimalListTableScrollPane.setName("uxAnimalListTableScrollPane"); // NOI18N

        uxAnimalListTable.setName("uxAnimalListTable"); // NOI18N
        uxAnimalListTableScrollPane.setViewportView(uxAnimalListTable);

        gridBagConstraints = new java.awt.GridBagConstraints();
        gridBagConstraints.gridx = 0;
        gridBagConstraints.gridy = 1;
        gridBagConstraints.fill = java.awt.GridBagConstraints.BOTH;
        gridBagConstraints.weightx = 1.0;
        gridBagConstraints.weighty = 1.0;
        uxAnimalPanel.add(uxAnimalListTableScrollPane, gridBagConstraints);

        uxMainTabbedPane.addTab(resourceMap.getString("uxAnimalPanel.TabConstraints.tabTitle"), uxAnimalPanel); // NOI18N

        uxMainSplitPane.setRightComponent(uxMainTabbedPane);

        gridBagConstraints = new java.awt.GridBagConstraints();
        gridBagConstraints.gridx = 0;
        gridBagConstraints.gridy = 0;
        gridBagConstraints.fill = java.awt.GridBagConstraints.BOTH;
        gridBagConstraints.anchor = java.awt.GridBagConstraints.NORTHWEST;
        gridBagConstraints.weightx = 1.0;
        gridBagConstraints.weighty = 1.0;
        getContentPane().add(uxMainSplitPane, gridBagConstraints);

        uxMainMenuBar.setName("uxMainMenuBar"); // NOI18N

        uxFileMenu.setText(resourceMap.getString("uxFileMenu.text")); // NOI18N
        uxFileMenu.setName("uxFileMenu"); // NOI18N

        uxNewMenu.setText(resourceMap.getString("uxNewMenu.text")); // NOI18N
        uxNewMenu.setName("uxNewMenu"); // NOI18N

        uxNewAquariumMenuItem.setAccelerator(javax.swing.KeyStroke.getKeyStroke(java.awt.event.KeyEvent.VK_N, java.awt.event.InputEvent.CTRL_MASK));
        uxNewAquariumMenuItem.setText(resourceMap.getString("uxNewAquariumMenuItem.text")); // NOI18N
        uxNewAquariumMenuItem.setName("uxNewAquariumMenuItem"); // NOI18N
        uxNewAquariumMenuItem.addActionListener(new java.awt.event.ActionListener() {
            public void actionPerformed(java.awt.event.ActionEvent evt) {
                uxNewAquariumMenuItemActionPerformed(evt);
            }
        });
        uxNewMenu.add(uxNewAquariumMenuItem);

        uxFileMenu.add(uxNewMenu);

        uxQuitMenuItem.setAccelerator(javax.swing.KeyStroke.getKeyStroke(java.awt.event.KeyEvent.VK_Q, java.awt.event.InputEvent.CTRL_MASK));
        uxQuitMenuItem.setText(resourceMap.getString("uxQuitMenuItem.text")); // NOI18N
        uxQuitMenuItem.setName("uxQuitMenuItem"); // NOI18N
        uxQuitMenuItem.addActionListener(new java.awt.event.ActionListener() {
            public void actionPerformed(java.awt.event.ActionEvent evt) {
                uxQuitMenuItemActionPerformed(evt);
            }
        });
        uxFileMenu.add(uxQuitMenuItem);

        uxMainMenuBar.add(uxFileMenu);

        uxEditMenu.setText(resourceMap.getString("uxEditMenu.text")); // NOI18N
        uxEditMenu.setName("uxEditMenu"); // NOI18N

        uxDatabaseMenuItem.setText(resourceMap.getString("uxDatabaseMenuItem.text")); // NOI18N
        uxDatabaseMenuItem.setName("uxDatabaseMenuItem"); // NOI18N
        uxDatabaseMenuItem.addActionListener(new java.awt.event.ActionListener() {
            public void actionPerformed(java.awt.event.ActionEvent evt) {
                uxDatabaseMenuItemActionPerformed(evt);
            }
        });
        uxEditMenu.add(uxDatabaseMenuItem);

        uxMainMenuBar.add(uxEditMenu);

        uxHelpMenu.setText(resourceMap.getString("uxHelpMenu.text")); // NOI18N
        uxHelpMenu.setName("uxHelpMenu"); // NOI18N

        uxAboutMenuItem.setText(resourceMap.getString("uxAboutMenuItem.text")); // NOI18N
        uxAboutMenuItem.setName("uxAboutMenuItem"); // NOI18N
        uxAboutMenuItem.addActionListener(new java.awt.event.ActionListener() {
            public void actionPerformed(java.awt.event.ActionEvent evt) {
                uxAboutMenuItemActionPerformed(evt);
            }
        });
        uxHelpMenu.add(uxAboutMenuItem);

        uxMainMenuBar.add(uxHelpMenu);

        setJMenuBar(uxMainMenuBar);

        pack();
    }// </editor-fold>//GEN-END:initComponents

	private void uxNewAquariumMenuItemActionPerformed(java.awt.event.ActionEvent evt)//GEN-FIRST:event_uxNewAquariumMenuItemActionPerformed
	{//GEN-HEADEREND:event_uxNewAquariumMenuItemActionPerformed
		new AquariumForm(this).setVisible(true);
	}//GEN-LAST:event_uxNewAquariumMenuItemActionPerformed

	private void uxWaterRefreshmentAddButtonActionPerformed(java.awt.event.ActionEvent evt)//GEN-FIRST:event_uxWaterRefreshmentAddButtonActionPerformed
	{//GEN-HEADEREND:event_uxWaterRefreshmentAddButtonActionPerformed
		AquariumRow arow = (AquariumRow) uxAquariumList.getSelectedValue();
		if (arow != null)
		{
			java.sql.Date date = new java.sql.Date(uxCalendarPanel.getDate().getTimeInMillis());

			WaterActionForm form = new WaterActionForm(this, (WaterRefreshmentRow) null, arow, date);
			form.setVisible(true);
		}
	}//GEN-LAST:event_uxWaterRefreshmentAddButtonActionPerformed

	private void uxActionsListValueChanged(javax.swing.event.ListSelectionEvent evt)//GEN-FIRST:event_uxActionsListValueChanged
	{//GEN-HEADEREND:event_uxActionsListValueChanged
		if (evt.getValueIsAdjusting())
		{
			Object object = uxWaterActionList.getSelectedValue();
			DefaultTableModel model = (DefaultTableModel) uxWaterValuesTable.getModel();
			model.setRowCount(0);
			uxWaterValuesScrollPane.setVisible(false);
			uxDescriptionTextArea.setText("");

			if (object instanceof ActionRow)
			{

				ActionRow row = (ActionRow) object;
				uxDescriptionTextArea.setText(row.getComment());
			}
			if (object instanceof WaterMeasurementRow)
			{
				uxWaterValuesScrollPane.setVisible(true);

				try
				{
					WaterMeasurementRow row = (WaterMeasurementRow) object;
					ArrayList<WaterMeasurementListRow> measurements = Database.getWaterMeasurementListTable().getByMeasurementID(row.getId());
					for (WaterMeasurementListRow listRow : measurements)
					{
						OptimalAquariumWaterConditionRow oawcr = Database.getOptimalAquariumWaterConditionTable().getByPrimaryKey(new SimpleEntry<Integer, String>(row.getAquarium().getId(), listRow.getWaterConditionRow().getName()));
						if (oawcr != null)
						{
							model.addRow(new Object[]
									{
										listRow.getWaterConditionRow().getName(), listRow.getValue(), oawcr.getMinValue(), oawcr.getMaxValue()
									});
						}
						else
						{
							model.addRow(new Object[]
									{
										listRow.getWaterConditionRow().getName(), listRow.getValue()
									});
						}
					}
				}
				catch (SQLException ex)
				{
					//todo: handle
				}
			}

			uxDetailsPanel.updateUI();
		}
	}//GEN-LAST:event_uxActionsListValueChanged

	private void uxWaterTestAddButtonActionPerformed(java.awt.event.ActionEvent evt)//GEN-FIRST:event_uxWaterTestAddButtonActionPerformed
	{//GEN-HEADEREND:event_uxWaterTestAddButtonActionPerformed
		AquariumRow arow = (AquariumRow) uxAquariumList.getSelectedValue();
		if (arow != null)
		{
			java.sql.Date date = new java.sql.Date(uxCalendarPanel.getDate().getTimeInMillis());

			WaterActionForm form = new WaterActionForm(this, (WaterMeasurementRow) null, arow, date);
			form.setVisible(true);
		}
	}//GEN-LAST:event_uxWaterTestAddButtonActionPerformed

	private void uxDatabaseMenuItemActionPerformed(java.awt.event.ActionEvent evt)//GEN-FIRST:event_uxDatabaseMenuItemActionPerformed
	{//GEN-HEADEREND:event_uxDatabaseMenuItemActionPerformed
		DatabaseForm df = new DatabaseForm((Window) this);
		df.setVisible(true);
	}//GEN-LAST:event_uxDatabaseMenuItemActionPerformed

	private void uxAddAnimalButtonActionPerformed(java.awt.event.ActionEvent evt)//GEN-FIRST:event_uxAddAnimalButtonActionPerformed
	{//GEN-HEADEREND:event_uxAddAnimalButtonActionPerformed
		Object selectedValue = uxAquariumList.getSelectedValue();
		if (selectedValue instanceof AquariumRow)
		{
			AquariumRow row = (AquariumRow) selectedValue;
			AddAnimalToAquariumForm form = new AddAnimalToAquariumForm(this, row);
			form.setVisible(true);
		}
	}//GEN-LAST:event_uxAddAnimalButtonActionPerformed

	private void uxQuitMenuItemActionPerformed(java.awt.event.ActionEvent evt)//GEN-FIRST:event_uxQuitMenuItemActionPerformed
	{//GEN-HEADEREND:event_uxQuitMenuItemActionPerformed
		dispose();
	}//GEN-LAST:event_uxQuitMenuItemActionPerformed

	private void uxAboutMenuItemActionPerformed(java.awt.event.ActionEvent evt)//GEN-FIRST:event_uxAboutMenuItemActionPerformed
	{//GEN-HEADEREND:event_uxAboutMenuItemActionPerformed
		AboutForm af = new AboutForm(this);
		af.setVisible(true);
	}//GEN-LAST:event_uxAboutMenuItemActionPerformed

	private void uxAquariumListValueChanged(//GEN-FIRST:event_uxAquariumListValueChanged
			javax.swing.event.ListSelectionEvent evt)
	{//GEN-HEADEREND:event_uxAquariumListValueChanged
		if (evt.getValueIsAdjusting()
				&& uxAquariumList.getSelectedValue() instanceof AquariumRow)
		{
			fillAnimalTab();
			uxAnimalListTable.setSelectedAquarium((AquariumRow) uxAquariumList.getSelectedValue());
			uxWaterActionList.setSelectedAquarium((AquariumRow) uxAquariumList.getSelectedValue());
		}
		fillActionList();
		setMarkedDates();
	}//GEN-LAST:event_uxAquariumListValueChanged

	@Override
	public void dispose()
	{
		try
		{
			Database.close();
		}
		catch (SQLException ex)
		{
			JOptionPane.showMessageDialog(this,
					ResourceBundle.getBundle("carassius.resources.Messages").getString("ShutDownDatabaseError"),
					ResourceBundle.getBundle("carassius.resources.Messages").getString("ShutDownDatabaseErrorTitle"),
					JOptionPane.ERROR_MESSAGE);
		}
		super.dispose();
	}
	//<editor-fold defaultstate="collapsed" desc="Variables declaration">
    // Variables declaration - do not modify//GEN-BEGIN:variables
    private javax.swing.JMenuItem uxAboutMenuItem;
    private javax.swing.JPanel uxActionButtonPanel;
    private javax.swing.JPanel uxActionsPanel;
    private javax.swing.JButton uxAddAnimalButton;
    private carassius.GUI.AnimalListTable uxAnimalListTable;
    private javax.swing.JScrollPane uxAnimalListTableScrollPane;
    private javax.swing.JPanel uxAnimalPanel;
    private carassius.GUI.AquariumList uxAquariumList;
    private javax.swing.JPanel uxAquariumPanel;
    private javax.swing.JScrollPane uxAquariumScrollPane;
    private carassius.GUI.Calendar.CalendarPanel uxCalendarPanel;
    private javax.swing.JMenuItem uxDatabaseMenuItem;
    private javax.swing.JScrollPane uxDescriptionScrollPane;
    private javax.swing.JTextArea uxDescriptionTextArea;
    private javax.swing.JPanel uxDetailsPanel;
    private javax.swing.JMenu uxEditMenu;
    private javax.swing.JMenu uxFileMenu;
    private javax.swing.JMenu uxHelpMenu;
    private javax.swing.JPanel uxLeftPanel;
    private javax.swing.JMenuBar uxMainMenuBar;
    private javax.swing.JSplitPane uxMainSplitPane;
    private javax.swing.JTabbedPane uxMainTabbedPane;
    private javax.swing.JPanel uxMeasurementPanel;
    private javax.swing.JMenuItem uxNewAquariumMenuItem;
    private javax.swing.JMenu uxNewMenu;
    private javax.swing.JList uxNotesList;
    private javax.swing.JPanel uxNotesPanel;
    private javax.swing.JScrollPane uxNotesScrollPane;
    private javax.swing.JPanel uxPlantsTabPanel;
    private javax.swing.JMenuItem uxQuitMenuItem;
    private carassius.GUI.WaterActionList uxWaterActionList;
    private javax.swing.JScrollPane uxWaterActionsScrollPane;
    private javax.swing.JButton uxWaterRefreshmentAddButton;
    private javax.swing.JButton uxWaterTestAddButton;
    private javax.swing.JScrollPane uxWaterValuesScrollPane;
    private javax.swing.JPanel uxWaterValuesTabPanel;
    private javax.swing.JTable uxWaterValuesTable;
    // End of variables declaration//GEN-END:variables
	//</editor-fold>

	//<editor-fold defaultstate="collapsed" desc="Events">
	@Override
	public void propertyChange(PropertyChangeEvent evt)
	{
		if (evt.getSource().equals(uxCalendarPanel))
		{
			DefaultTableModel model = (DefaultTableModel) uxWaterValuesTable.getModel();
			model.setRowCount(0);
			uxDescriptionTextArea.setText("");
			uxWaterActionList.setSelectedDate(uxCalendarPanel.getDate());
			fillActionList();
		}
	}

	@Override
	public void stateChanged(ChangeEvent e)
	{
		if (e.getSource() == uxMainTabbedPane)
		{
			fillAnimalTab();
		}
	}

	//<editor-fold defaultstate="collapsed" desc="Aquarium">
	@Override
	public void aquariumAdded(AquariumRow row)
	{
		DefaultListModel model = (DefaultListModel) uxAquariumList.getModel();
		model.addElement(row);
	}

	@Override
	public void aquariumRemoved(AquariumRow row)
	{
		removeAquariumFromList(row);
	}
	//</editor-fold>

	//<editor-fold defaultstate="collapsed" desc="OrganismList">
	@Override
	public void organismListAdded(OrganismListRow row)
	{
		if (row.getAquarium().equals((AquariumRow) uxAquariumList.getSelectedValue())
				&& uxMainTabbedPane.getSelectedComponent() == uxAnimalPanel)
		{
			addOrganismListToAnimalTable(row);
		}
	}

	@Override
	public void organismListRemoved(OrganismListRow row)
	{
		if (row.getAquarium().equals(uxAquariumList.getSelectedValue())
				&& uxMainTabbedPane.getSelectedComponent() == uxAnimalPanel)
		{
			DefaultTableModel model = (DefaultTableModel) uxAnimalListTable.getModel();
			for (int i = model.getRowCount() - 1; i >= 0; i--)
			{
				if (row.equals(model.getValueAt(i, 0)))
				{
					uxAnimalListTable.getCellEditor(i, 0).cancelCellEditing();
					model.removeRow(i);
				}
			}
		}
	}
	//</editor-fold>

	//<editor-fold defaultstate="collapsed" desc="Water Measurement">
	@Override
	public void waterMeasurementAdded(WaterMeasurementRow row)
	{
		if (uxMainTabbedPane.getSelectedComponent() == uxWaterValuesTabPanel
				&& uxAquariumList.getSelectedValue() instanceof AquariumRow
				&& uxAquariumList.getSelectedValue().equals(row.getAquarium()))
		{
			DefaultListModel model = (DefaultListModel) uxWaterActionList.getModel();
			model.addElement(row);
			uxCalendarPanel.addMarkedDate(row.getDate().getTime());
		}
	}

	@Override
	public void waterMeasurementRemoved(WaterMeasurementRow row)
	{
		if (uxMainTabbedPane.getSelectedComponent() == uxWaterValuesTabPanel
				&& uxAquariumList.getSelectedValue() instanceof AquariumRow
				&& uxAquariumList.getSelectedValue().equals(row.getAquarium()))
		{
			DefaultListModel model = (DefaultListModel) uxWaterActionList.getModel();
			model.removeElement(row);
			uxCalendarPanel.removeMarkedDate(row.getDate().getTime());
		}
	}
	//</editor-fold>

	//<editor-fold defaultstate="collapsed" desc="Water Refreshment">
	@Override
	public void waterRefreshmentAdded(WaterRefreshmentRow row)
	{
		if (uxMainTabbedPane.getSelectedComponent() == uxWaterValuesTabPanel
				&& uxAquariumList.getSelectedValue() instanceof AquariumRow
				&& uxAquariumList.getSelectedValue().equals(row.getAquarium()))
		{
			DefaultListModel model = (DefaultListModel) uxWaterActionList.getModel();
			model.addElement(row);
			uxCalendarPanel.addMarkedDate(row.getDate().getTime());
		}
	}

	@Override
	public void waterRefreshmentRemoved(WaterRefreshmentRow row)
	{
		if (uxMainTabbedPane.getSelectedComponent() == uxWaterValuesTabPanel
				&& uxAquariumList.getSelectedValue() instanceof AquariumRow
				&& uxAquariumList.getSelectedValue().equals(row.getAquarium()))
		{
			DefaultListModel model = (DefaultListModel) uxWaterActionList.getModel();
			model.removeElement(row);
			uxCalendarPanel.removeMarkedDate(row.getDate().getTime());
		}
	}
	//</editor-fold>
	//</editor-fold>
}
